<?php
namespace app\service;

use app\model\CamperModel;
use app\model\DistributionOfficerModel;
use app\model\GoodsModel;
use app\model\GoodsPeriodModel;
use app\model\GoodsSpecificationModel;
use app\model\MembersRelationModel;
use app\model\OrderDetailsModel;
use app\model\OrderDistributionModel;
use app\model\OrderInvoiceModel;
use app\model\OrderModel;
use app\model\OrderPeriodProcessModel;
use app\model\OrderProfitProcessModel;
use app\model\OrderRefundModel;
use support\Db;
use support\facade\Logger;
use const support\AUTO_CLOSE_ORDER_QUEUE;
use const support\AUTO_HANDLE_ORDER_PROFIT_QUEUE;
use const support\AUTO_HANDLE_ORDER_REFUND_QUEUE;
use const support\CORRECT;
use const support\DENY;
use const support\env_test_order_commission_amount;
use const support\env_test_order_payment_amount;
use const support\ERROR;
use const support\GOODS_STOCK_NUM_LACK;
use const support\identity_type_remarks;
use const support\OPERATE_ERROR;
use const support\ORDER_CREATE_FAIL;
use const support\ORDER_INVALID;
use const support\ORDER_JOIN_LACK;
use const support\ORDER_OVERTIME;
use const support\order_process_status_1;
use const support\order_process_status_2;
use const support\order_process_status_3;
use const support\order_process_status_4;
use const support\order_refund_auto_handle_interval;
use const support\ORDER_REFUND_CREATE_FAIL;
use const support\order_status_0;
use const support\order_status_1;
use const support\order_status_2;
use const support\order_status_3;
use const support\order_status_8;
use const support\order_status_9;
use const support\order_step_status_1;
use const support\order_step_status_2;
use const support\order_step_status_3;
use const support\order_step_status_4;
use const support\order_step_status_5;
use const support\order_step_status_6;
use const support\order_step_status_7;
use const support\order_step_status_8;
use const support\order_step_status_desc_remarks;
use const support\order_step_status_remarks;
use const support\PARAMETER_ERROR;
use const support\pay_type_1;
use const support\refund_rule_1;
use const support\refund_rule_2;
use const support\refund_rule_5;
use const support\transfer_account_default;
use const support\unpaid_order_auto_cancel_interval;
use Webman\RedisQueue\Client;

class OrderService
{

    //商品预下单
    public static function orderToPrePayCalculate(array $data): array
    {
        try {
            //计算本次待购买总数量
            $buyTotalNum=array_sum(array_column($data['specifications'],'num'));
            //获取人员类型购买数量
            $buyNumByTypes=array_column($data['specifications'],'num','type');
            //获取商品信息
            $goods=GoodsModel::where([
                'id'        =>$data['goods_id'],
                'status'    =>CORRECT,
                'is_upper'  =>CORRECT
            ])->select(['id','goods_stock_num','is_upper','is_enroll_period'])->first();
            if (empty($goods->id)){
                Logger::app('订单预下单:无效营期ID','info',$data);
                return formatReturnData(PARAMETER_ERROR,'无效营期ID');
            }
            if ($goods->is_upper!=CORRECT){
                Logger::app('订单预下单:商品已下架');
                return formatReturnData(PARAMETER_ERROR,'该商品已下架');
            }
            if ($goods->is_enroll_period==CORRECT){
                if (empty($data['goods_period_id'])){
                    return formatReturnData(PARAMETER_ERROR,'报名日期不能为空');
                }
                //获取营期信息
                $goodsPeriod=GoodsPeriodModel::where([
                    'id'        =>$data['goods_period_id'],
                    'status'    =>CORRECT
                ])->select(['id','goods_stock_num'])->first();
                if (empty($goodsPeriod->id)){
                    Logger::app('订单预下单:无效营期ID','info',$data);
                    return formatReturnData(PARAMETER_ERROR,'无效营期ID');
                }
                //计算库存是否够用
                if ($goodsPeriod->goods_stock_num<$buyTotalNum){
                    Logger::app('订单预下单:营期商品库存不足','info',[$goodsPeriod->goods_stock_num,$buyTotalNum]);
                    return formatReturnData(GOODS_STOCK_NUM_LACK,'商品库存不足');
                }
                $data['goods_stock_num']=$goodsPeriod->goods_stock_num;
            }else{
                $data['goods_period_id']=0;
                //计算库存是否够用
                if ($goods->goods_stock_num<$buyTotalNum){
                    Logger::app('订单预下单:商品库存不足','info',[$goods->goods_stock_num,$buyTotalNum]);
                    return formatReturnData(GOODS_STOCK_NUM_LACK,'商品库存不足');
                }
                $data['goods_stock_num']=$goods->goods_stock_num;
            }
            //查询规格信息
            $goodsSpecifications=GoodsSpecificationModel::where([
                'goods_id'=>$data['goods_id'],
                'status'  =>CORRECT
            ])->pluck('goods_sale_price','type')->toArray();
            if (empty($goodsSpecifications)){
                Logger::app('订单预下单:规格信息无效','info',$data);
                return formatReturnData(PARAMETER_ERROR,'商品规格无效');
            }
            //计算金额
            $totalMoneyNum=0;
            $buyDetails=[];
            foreach ($buyNumByTypes as $type=>$buyNum){
                if (!$buyNum){
                    continue;
                }
                $goodsSalePrice=$goodsSpecifications[$type]??0;
                $moneyNum=$goodsSalePrice*$buyNum;
                $totalMoneyNum+=$moneyNum;
                $buyDetails[]=[
                    'type'=>$type,
                    'type_name'=>identity_type_remarks[$type]??'',
                    'num' =>$buyNum,
                    'goods_sale_price'=>$goodsSalePrice,
                    'money_num'=>number_format($moneyNum, 2, '.', '')
                ];
            }
            $data['buy_details']=$buyDetails;
            $data['total_buy_num']=$buyTotalNum;
            $data['total_money_num']=number_format($totalMoneyNum, 2, '.', '');
            return formatReturnSuccessData($data);
        }catch (\Throwable $e){
            Logger::app($e);
            return formatReturnData(ERROR,$e->getMessage());
        }
    }


    //商品下单
    public static function orderToPayCalculate(int $memberId,array $data): array
    {
        //获取购买基础信息
        list($retCode,$msg,$retData)=OrderService::orderToPrePayCalculate($data);
        if ($retCode){
            return formatReturnData($retCode,$msg,$retData);
        }
        if ($retData['total_buy_num']!=count($data['joins'])){
            return formatReturnData(ORDER_JOIN_LACK);
        }
        //查询商品信息
        $goods=GoodsModel::where('id',$data['goods_id'])->first()->toArray();
        $goodsPeriods=[];
        if ($goods['is_enroll_period']==CORRECT){
            //查询营期信息
            $goodsPeriods=GoodsPeriodModel::where([
                'goods_id'=>$data['goods_id'],
                'status'  =>CORRECT
            ])->select(['id','goods_period_date','goods_period_title','goods_stock_num'])->get()->toArray();
            $goodsPeriodsDataArr=$goodsPeriods?array_column($goodsPeriods,'goods_period_date','id'):[];
            $goodsPeriodsArr=$goodsPeriods?array_column($goodsPeriods,'goods_period_title','id'):[];
            $goodsPeriodStockNums=$goodsPeriods?array_column($goodsPeriods,'goods_stock_num','id'):[];
            Logger::app('商品下单:营期库存信息','info',$goodsPeriodStockNums);
        }
        //检测库存是否存在
        if ($goods['goods_stock_num']<$retData['total_buy_num']){
            Logger::app('商品下单:检测库存不足1','info',[$goods['goods_stock_num'],$retData['total_buy_num']]);
            return formatReturnData(GOODS_STOCK_NUM_LACK);
        }
        $goodsPeriodStockNum=$goodsPeriodStockNums[$data['goods_period_id']]??0;
        if ($data['goods_period_id'] && (empty($goodsPeriodStockNum) || $goodsPeriodStockNum<$retData['total_buy_num'])){
            Logger::app('商品下单:检测库存不足2','info',[$goodsPeriodStockNum,$retData['total_buy_num']]);
            return formatReturnData(GOODS_STOCK_NUM_LACK);
        }
        //查询参与者信息
        $joinDetails=CamperModel::whereIn('id',$data['joins'])->where('status',CORRECT)
            ->get()->toArray();
        $joinUserTypeNums=$joinDetails?array_count_values(array_column($joinDetails,'member_type')):[];
        $joinMemberNums=[];
        foreach ($joinUserTypeNums as $type=>$typeNum){
            $joinMemberNums[]=[
                'member_type'       =>$type,
                'member_type_title' =>identity_type_remarks[$type]??'',
                'num'               =>$typeNum
            ];
        }
        //查询规格信息
        $goodsSpecifications=GoodsSpecificationModel::where([
            'goods_id'=>$data['goods_id'],
            'status'  =>CORRECT
        ])->select(['id','goods_sale_price','goods_original_price','type'])->get()->toArray();

        //查询用户关系绑定
        $pid=MembersRelationModel::where([
            'member_id'=>$memberId,
            'status'=>CORRECT
        ])->value('pid')?:0;
        Db::beginTransaction();
        //检测是否启用分账模式
        $isAllowProfit=DENY;
        if ($goods['is_allocation_mode']==CORRECT || $goods['is_repurchase_allocation_mode']==CORRECT){
            $isAllowProfit=CORRECT;
        }
        try {
            $totalFee=checkRuntimeEnv()?$retData['total_money_num']:env_test_order_payment_amount;
            //创建订单
            $orderInsertData=[
                'order_sn'              =>createOrderSn(),
                'goods_id'              =>$data['goods_id'],
                'goods_icon'            =>$goods['goods_icon'],
                'goods_period_id'       =>$data['goods_period_id'],
                'goods_period_title'    =>$goodsPeriodsArr[$data['goods_period_id']]??'',
                'goods_period_date'     =>$goodsPeriodsDataArr[$data['goods_period_id']]??0,
                'goods_num'             =>$retData['total_buy_num'],
                'join_member_nums'      =>json_encode($joinMemberNums,JSON_UNESCAPED_UNICODE),
                'goods_title'           =>$goods['goods_title'],
                'goods_sn'              =>$goods['goods_sn'],
                'order_amount'          =>$retData['total_money_num'],
                'order_actual_amount'   =>$totalFee,
                'order_remark'          =>$data['order_remark'],
                'pay_type'              =>pay_type_1,
                'member_id'             =>$memberId,
                'order_trade_no'        =>createOrderTradeNo(),
                'pid'                   =>$pid,
                'assembly_location_id'  =>$goods['assembly_location_id'],
                'create_time'           =>time(),
                'is_allow_profit'       =>$isAllowProfit
            ];
            $orderId=OrderModel::insertGetId($orderInsertData);
            if (!$orderId){
                Db::rollBack();
                Logger::app('商品下单:创建主表订单失败','info',$orderInsertData);
                return formatReturnData(ORDER_CREATE_FAIL);
            }
            $orderInsertData['order_id']=$orderId;
            //创建订单拓展详情
            $goodsDetails=[
                'goods'                 =>$goods,
                'goods_periods'         =>$goodsPeriods,
                'goods_specifications'  =>$goodsSpecifications
            ];

            $orderDetailsInsertData=[
                'order_id'      =>$orderId,
                'member_id'     =>$memberId,
                'goods_details' =>json_encode($goodsDetails,JSON_UNESCAPED_UNICODE),
                'join_details'  =>json_encode($joinDetails,JSON_UNESCAPED_UNICODE),
                'create_time'   =>time()
            ];
            $orderDetailsId=OrderDetailsModel::insertGetId($orderDetailsInsertData);
            if (!$orderDetailsId){
                Db::rollBack();
                Logger::app('商品下单:创建子表订单失败','info',$orderDetailsInsertData);
                return formatReturnData(ORDER_CREATE_FAIL);
            }
            //生成微信支付参数
            $orderPayment=WechatPayService::getToPayParamsWithDivideAccounts($memberId,$orderInsertData['order_trade_no'],$data['trade_type'],$orderInsertData['order_actual_amount'],$orderInsertData['goods_title']);
            if (!$orderPayment){
                Db::rollBack();
                Logger::app('商品下单:创建支付信息失败');
                return formatReturnData(ORDER_CREATE_FAIL);
            }
            Db::commit();
            unset($orderInsertData['join_member_nums']);
            $orderPayment['order']=$orderInsertData;
            $orderPayment['join_details']= array_map(function($row) {
                return [
                    'id'            => $row['id'],
                    'real_name'     => $row['real_name'],
                    'card_number'   => $row['card_number'],
                    'member_type'   => $row['member_type'],
                    'member_type_title'=>identity_type_remarks[$row['member_type']]??''
                ];
            }, $joinDetails);
            $orderPayment['auto_cancel_interval']=unpaid_order_auto_cancel_interval;
            //设置自动关闭订单任务
            Client::send(AUTO_CLOSE_ORDER_QUEUE, ['order_id'=>$orderId], unpaid_order_auto_cancel_interval);
            return formatReturnSuccessData($orderPayment);
        }catch (\Throwable $e){
            Db::rollBack();
            Logger::app($e);
            return formatReturnData(ORDER_CREATE_FAIL,$e->getMessage());
        }
    }

    //订单当前所处步骤状态
    public static function orderStepStatusTip($orderStatus,$isRefund,$isVerification,$isComment,$isInvoice): array
    {
        $statusTips=[
            'is_allow_refund'=>DENY,
            'is_allow_comment'=>DENY,
            'is_allow_reset_pay'=>DENY,
            'is_allow_invoice'=>DENY,
        ];
        if ($orderStatus==order_status_0){
            $statusTips['status']=order_step_status_1;
            $statusTips['title']=order_step_status_remarks[order_step_status_1];
            $statusTips['desc']=order_step_status_desc_remarks[order_step_status_1];
            $statusTips['is_allow_reset_pay']=CORRECT;
        }elseif ($orderStatus==order_status_1){
            if ($isRefund==1){
                $statusTips['status']=order_step_status_3;
                $statusTips['title']=order_step_status_remarks[order_step_status_3];
                $statusTips['desc']=order_step_status_desc_remarks[order_step_status_3];
                $statusTips['is_allow_refund']=CORRECT;
            }else{
                $statusTips['status']=order_step_status_4;
                $statusTips['title']=order_step_status_remarks[order_step_status_4];
                $statusTips['desc']=order_step_status_desc_remarks[order_step_status_4];
            }
        }elseif ($orderStatus==order_status_9){
            if ($isRefund==4){
                $statusTips['status']=order_step_status_5;
                $statusTips['title']=order_step_status_remarks[order_step_status_5];
                $statusTips['desc']=order_step_status_desc_remarks[order_step_status_5];
            }elseif ($isRefund==3){
                $statusTips['status']=order_step_status_6;
                $statusTips['title']=order_step_status_remarks[order_step_status_6];
                $statusTips['desc']=order_step_status_desc_remarks[order_step_status_6];
            }
        }elseif ($orderStatus==order_status_2 || $orderStatus==order_status_3){
            $statusTips['status']=order_step_status_2;
            $statusTips['title']=order_step_status_remarks[order_step_status_2];
            $statusTips['desc']=order_step_status_desc_remarks[order_step_status_2];
            $statusTips['is_allow_refund']=DENY;
        }elseif ($orderStatus==order_status_8){
            if ($isComment==1){
                $statusTips['status']=order_step_status_8;
                $statusTips['title']=order_step_status_remarks[order_step_status_8];
                $statusTips['desc']=order_step_status_desc_remarks[order_step_status_8];
            }else{
                $statusTips['status']=order_step_status_7;
                $statusTips['title']=order_step_status_remarks[order_step_status_7];
                $statusTips['desc']=order_step_status_desc_remarks[order_step_status_7];
                $statusTips['is_allow_comment']=CORRECT;
            }
            if ($isInvoice==1){
                $statusTips['is_allow_invoice']=CORRECT;
            }
        }
        return $statusTips;
    }

    //订单列表
    public static function orderLists(int $memberId,int $orderProcessStatus,int $page,int $limit): array
    {
        //订单查询
        $order=OrderModel::where([
            'member_id'=>$memberId,
            'status'   =>CORRECT
        ]);
        //确定筛选的订单状态
        if ($orderProcessStatus==order_process_status_1){
            $orderStatus=[order_status_0];
            $order=$order->whereIn('order_status',$orderStatus);
        }elseif ($orderProcessStatus==order_process_status_2){
            $orderStatus=[order_status_1];
            $order=$order->whereIn('order_status',$orderStatus);
        }elseif ($orderProcessStatus==order_process_status_3){
            $orderStatus=[order_status_8];
            $order=$order->whereIn('order_status',$orderStatus);
        }elseif ($orderProcessStatus==order_process_status_4){
            $orderStatus=[order_status_1,order_status_8];
            $order=$order->whereIn('order_status',$orderStatus)->whereIn('is_refund',[2,3]);
        }
        //计算总数量
        $totalNum=$order->count();
        $offset=($page-1)*$limit;
        $orders=$order->offset($offset)->limit($limit)->select([
            'id','order_sn','goods_id','goods_num','goods_title','goods_icon','order_amount','order_actual_amount','is_verification',
            'order_remark','pay_time','is_refund','refund_time','order_status','create_time','goods_period_date','join_member_nums','is_comment','is_invoice'
        ])->orderBy('id','desc')->get()->toArray();
        $orders=array_map(function($row) {
            $stepInfo=OrderService::orderStepStatusTip($row['order_status'],$row['is_refund'],$row['is_verification'],$row['is_comment'],$row['is_invoice']);
            //确定当前进程状态
            $row['order_step_status']=$stepInfo['status'];
            //确定当前进程标题
            $row['order_step_status_title']=$stepInfo['title'];
            $row['is_allow_refund']=$stepInfo['is_allow_refund'];
            if ($row['is_allow_refund']==CORRECT){
                $row['is_allow_refund']=(($row['goods_period_date']-86400)>time())?CORRECT:DENY;
            }
            $row['is_allow_comment']=$stepInfo['is_allow_comment'];
            $row['is_allow_reset_pay']=$stepInfo['is_allow_reset_pay'];
            $row['is_allow_invoice']=$stepInfo['is_allow_invoice'];
            return $row;
        }, $orders);
        return commonPagingData($orders,$page,$limit,$totalNum);
    }

    //订单详情
    public static function orderDetails(int $memberId,int $orderId): array
    {
        $order=OrderModel::with([
            'orderDetails',
            'assemblyDetails'=>function($query){
                $query->select(['id','location_name','location_province','location_city','location_area','location_address','contacts_name','contacts_mobile']);
            }
        ])->where([
            'id'            =>$orderId,
            'member_id'     =>$memberId,
            'status'        =>CORRECT
        ])->select([
            'id','order_sn','goods_id','goods_period_id','goods_period_date','goods_period_title','goods_num','join_member_nums',
            'goods_title','goods_icon','goods_sn','order_amount','order_actual_amount','order_remark','pay_type',
            'order_trade_no','pay_time','is_verification','verification_time','is_comment','is_refund','refund_time',
            'order_status','create_time', 'assembly_location_id','pay_time','is_invoice'
        ])->first();
        if (empty($order->id)){
            Logger::app('订单详情:订单ID无效');
            return formatReturnData(ORDER_CREATE_FAIL,'该订单已失效');
        }
        $order=$order->toArray();
        //获取规格信息
        $goodsSpecifications=$order['order_details']['goods_details']['goods_specifications']??[];
        $goodsSpecificationData=array_column($goodsSpecifications,'goods_sale_price','type');
        //订单详情
        $joinDetails=$order['order_details']['join_details']??[];
        $order['join_details']= array_map(function($row)use($goodsSpecificationData) {
            return [
                'id'            => $row['id'],
                'real_name'     => $row['real_name'],
                'card_number'   => $row['card_number'],
                'member_type'   => $row['member_type'],
                'member_type_title'=>identity_type_remarks[$row['member_type']]??'',
                'sale_price'    =>$goodsSpecificationData[$row['member_type']]??''
            ];
        }, $joinDetails);
        unset($order['order_details']);
        //状态转换
        $tips=OrderService::orderStepStatusTip($order['order_status'],$order['is_refund'],$order['is_verification'],$order['is_comment'],$order['is_invoice']);
        //生成核验二维码
        $order['verification_qrcode']='';
        if ($tips['status']==order_step_status_3){
            $order['verification_qrcode']=generate_base64_qrcode($order['order_sn']);
            $tips['desc']=sprintf($tips['desc'],!empty($order['goods_period_date'])?date('Y/m/d',$order['goods_period_date']):'');
        }
        $order['order_step_status']=$tips['status'];
        $order['order_step_status_title']=$tips['title'];
        $order['order_step_status_desc']=$tips['desc'];
        $order['is_allow_refund']=$tips['is_allow_refund'];
        if ($order['is_allow_refund']==CORRECT){
            $order['is_allow_refund']=(($order['goods_period_date']-86400)>time())?CORRECT:DENY;
        }
        $order['is_allow_comment']=$tips['is_allow_comment'];
        $order['is_allow_reset_pay']=$tips['is_allow_reset_pay'];
        $order['is_allow_invoice']=$tips['is_allow_invoice'];
        return formatReturnSuccessData($order);
    }

    //售后详情
    public static function orderRefundDetails(int $memberId,int $orderId): array
    {
        $order=OrderModel::with([
            'orderDetails'
        ])->where([
            'id'            =>$orderId,
            'member_id'     =>$memberId,
            'status'        =>CORRECT
        ])->where('is_refund','>',1)->select([
            'id','order_sn','goods_id','goods_period_id','goods_period_date','goods_period_title','goods_num','join_member_nums',
            'goods_title','goods_icon','goods_sn','order_amount','order_actual_amount','order_remark','pay_type',
            'order_trade_no','pay_time','is_verification','verification_time','is_comment','is_refund',
            'order_status','create_time','pay_time','is_invoice'
        ])->first();
        if (empty($order->id)){
            Logger::app('订单详情:订单ID无效');
            return formatReturnData(ORDER_INVALID,'该订单已失效');
        }
        $order=$order->toArray();
        //获取规格信息
        $goodsSpecifications=$order['order_details']['goods_details']['goods_specifications']??[];
        $goodsSpecificationData=array_column($goodsSpecifications,'goods_sale_price','type');
        //订单详情
        $joinDetails=$order['order_details']['join_details']??[];
        $order['join_details']= array_map(function($row)use($goodsSpecificationData) {
            return [
                'id'            => $row['id'],
                'real_name'     => $row['real_name'],
                'card_number'   => $row['card_number'],
                'member_type'   => $row['member_type'],
                'member_type_title'=>identity_type_remarks[$row['member_type']]??'',
                'sale_price'    =>$goodsSpecificationData[$row['member_type']]??''
            ];
        }, $joinDetails);
        //状态转换
        $tips=OrderService::orderStepStatusTip($order['order_status'],$order['is_refund'],$order['is_verification'],$order['is_comment'],$order['is_invoice']);
        $order['order_step_status']=$tips['status'];
        $order['order_step_status_title']=$tips['title'];
        $order['order_step_status_desc']=$tips['desc'];
        unset($order['order_details']);
        //实际退款金额
        $order['order_refund_amount']=OrderRefundModel::where([
            'order_id'=>$order['id']
        ])->value('order_refund_amount')?:0;
        return formatReturnSuccessData($order);
    }

    //重新支付
    public static function orderResetPay(int $memberId,int $orderId,string $tradeType): array
    {
        //获取交易流水支付状态
        $order=OrderModel::where([
            'id'            =>$orderId,
            'member_id'     =>$memberId,
            'status'        =>CORRECT,
            'order_status'  =>order_status_0
        ])->first();
        if (empty($order->id)){
            Logger::app('重新支付:订单ID无效');
            return formatReturnData(ORDER_OVERTIME,'该订单已超时');
        }
        $order=$order->toArray();

        //查询库存是否充足
        $goods=GoodsModel::where('id',$order['goods_id'])->first()->toArray();
        $goodsPeriodStockNum=0;
        if ($goods['is_enroll_period']==CORRECT){
            //查询营期信息
            $goodsPeriodStockNum=GoodsPeriodModel::where([
                'goods_id'  =>$order['goods_id'],
                'status'    =>CORRECT,
                'id'        =>$order['goods_period_id']
            ])->value('goods_stock_num')?:0;
        }
        if ($goods['goods_stock_num']<$order['goods_num']){
            Logger::app('商品下单:检测库存不足1','info',[$goods['goods_stock_num'],$order['goods_num']]);
            return formatReturnData(GOODS_STOCK_NUM_LACK);
        }
        if (!$order['goods_period_id'] && (empty($goodsPeriodStockNum) || $goodsPeriodStockNum<$order['goods_num'])){
            Logger::app('商品下单:检测库存不足2','info',[$goodsPeriodStockNum,$order['goods_num']]);
            return formatReturnData(GOODS_STOCK_NUM_LACK);
        }

        //查询
        $orderDetails=OrderDetailsModel::where([
            'order_id'      =>$orderId,
            'status'        =>CORRECT
        ])->select(['id','join_details'])->first();
        if (empty($orderDetails->id)){
            Logger::app('重新支付:订单详情无效');
            return formatReturnData(ORDER_INVALID,'该订单已失效');
        }
        $orderDetails=$orderDetails->toArray();
        //生成新第三方流水号
        $order['order_trade_no']=createOrderTradeNo();
        Db::beginTransaction();
        try {
            $totalFee=checkRuntimeEnv()?$order['order_actual_amount']:env_test_order_payment_amount;
            //生成微信支付参数
            $orderPayment=WechatPayService::getToPayParamsWithDivideAccounts($memberId,$order['order_trade_no'],$tradeType,$totalFee,$order['goods_title'],$order['is_profit']);
            if (!$orderPayment){
                Db::rollBack();
                Logger::app('商品下单:创建支付信息失败');
                return formatReturnData(ORDER_CREATE_FAIL);
            }
            $ret=OrderModel::where('id',$orderId)->update([
                'order_trade_no'=>$order['order_trade_no'],
                'update_time'   =>time()
            ]);
            if (!$ret){
                Db::rollBack();
                Logger::app('商品下单:创建支付信息失败');
                return formatReturnData(ORDER_CREATE_FAIL);
            }
            Db::commit();
            $orderPayment['order']=$order;
            $orderPayment['join_details']= array_map(function($row) {
                return [
                    'id'            => $row['id'],
                    'real_name'     => $row['real_name'],
                    'card_number'   => $row['card_number'],
                    'member_type'   => $row['member_type'],
                    'member_type_title'=>identity_type_remarks[$row['member_type']]??''
                ];
            }, $orderDetails['join_details']);
            $orderPayment['auto_cancel_interval']=unpaid_order_auto_cancel_interval;
            //设置自动关闭订单任务
            Client::send(AUTO_CLOSE_ORDER_QUEUE, ['order_id'=>$orderId], unpaid_order_auto_cancel_interval);
            return formatReturnSuccessData($orderPayment);
        }catch (\Throwable $e){
            Db::rollBack();
            Logger::app($e);
            return formatReturnData(ORDER_CREATE_FAIL,$e->getMessage());
        }
    }

    //申请开票
    public static function toOrderInvoice(int $memberId,array $data): array
    {
        //检测订单是否可开具发票
        $isInvoice=OrderModel::where([
            'id'        =>$data['order_id'],
            'member_id' =>$memberId,
        ])->value('is_invoice');
        if ($isInvoice>1){
            return formatReturnData(PARAMETER_ERROR,'该订单已开具过发票');
        }
        Db::beginTransaction();
        try {
            $data['member_id']=$memberId;
            //新增发票信息
            $ret1=OrderInvoiceModel::insertGetId($data);
            if (!$ret1){
                Db::rollBack();
                Logger::app('申请开票:新增发票信息失败');
                return formatReturnData(OPERATE_ERROR);
            }
            //联动订单状态
            $ret2=OrderModel::where([
                'id'  =>$data['order_id'],
                'member_id' =>$memberId,
            ])->update([
                'is_invoice'    =>2,
                'update_time'   =>time()
            ]);
            if (!$ret2){
                Db::rollBack();
                Logger::app('申请开票:联动订单状态失败');
                return formatReturnData(OPERATE_ERROR);
            }
            Db::commit();
            return formatReturnSuccessData();
        }catch (\Throwable $e){
            Db::rollBack();
            Logger::app($e);
            return formatReturnData(ORDER_CREATE_FAIL,$e->getMessage());
        }
    }

    //申请开票历史记录
    public static function getOrderInvoiceHistory(int $memberId): array
    {
        $obj= OrderInvoiceModel::where([
            'member_id'=>$memberId
        ])->orderBy('id','desc')->first();
        return !empty($obj->id)?$obj->toArray():[];
    }

    //申请退款操作
    public static function toApplyRefund(int $memberId,int $orderId,string $orderRefundDesc='',bool $isDirect=false): array
    {
        var_dump($memberId,$orderId);
        //查询是否符合退款要求
        $order=OrderModel::where([
            'id'        =>$orderId,
            'member_id' =>$memberId,
            'is_refund' =>CORRECT
        ])->whereIn('order_status',[order_status_1,order_status_8])->first();
        if (empty($order->id)){
            Logger::app('申请退款操作:无效订单');
            return formatReturnData(PARAMETER_ERROR,'该退单ID无效');
        }
        if (!$isDirect){
            //计算本次分账涉及金额
            $refund=RefundRulesService::refundAlgorithmV1($order['order_actual_amount'],$order['goods_period_date']);
            Logger::app('申请退款操作:计算本次分账涉及金额','info',$refund);
            if (empty($refund['actual_refund_amount'])){
                Logger::app('申请退款操作:不符合退单要求');
                return formatReturnData(PARAMETER_ERROR,'该订单不支持退款');
            }
        }else{
            $refund['actual_refund_amount']=$order->order_actual_amount;
            $refund['refund_rule_type']=refund_rule_5;
        }

        Db::beginTransaction();
        try {
            $refundNo=order_no();
            //创建退款订单信息
            $ret=OrderRefundModel::insertGetId([
                'order_id'              =>$orderId,
                'member_id'             =>$memberId,
                'order_refund_sn'       =>$refundNo,
                'order_receipt_amount'  =>$order->order_actual_amount,
                'order_refund_amount'   =>$refund['actual_refund_amount'],
                'order_deduction_type'  =>$refund['refund_rule_type'],
                'order_refund_desc'     =>$orderRefundDesc,
                'create_time'           =>time()
            ]);
            if (!$ret){
                Db::rollBack();
                Logger::app('申请退款操作:创建退单数据失败');
                return formatReturnData(OPERATE_ERROR);
            }
            //更新主订单信息
            $order->is_refund=2;
            $order->update_time=time();
            if (!$order->save()){
                Db::rollBack();
                Logger::app('申请退款操作:更新主订单信息失败');
                return formatReturnData(OPERATE_ERROR);
            }
            Db::commit();
            //设置自动退款任务
            Client::send(AUTO_HANDLE_ORDER_REFUND_QUEUE, ['member_id'=>$memberId,'refund_no'=>$refundNo], order_refund_auto_handle_interval);
            return formatReturnSuccessData();
        }catch (\Throwable $e){
            Db::rollBack();
            Logger::app($e);
            return formatReturnData(ORDER_REFUND_CREATE_FAIL,$e->getMessage());
        }
    }

    //计算并分销金额数据
    public static function calculateDistributionCommission(int $orderId){
        //查询订单信息
        $order = OrderModel::where('id',$orderId)->first();
        if (empty($order->id)){
            return false;
        }
        $order=$order->toArray();
        //查询用户是否复购
        $onceNum=OrderModel::where([
            'member_id'=>$order['member_id']
        ])->whereIn('order_status',[order_status_1,order_status_8])->count()?:0;
        //查询商品最新信息
        $goods=GoodsModel::where('id',$order['goods_id'])->select([
            'is_allocation_mode','allocation_rate','allocation_amount','is_repurchase_allocation_mode',
            'repurchase_allocation_rate','repurchase_allocation_amount'
        ])->first()->toArray();
        //计算分佣金额
        $insert['order_id']=$orderId;
        $insert['order_receipt_amount']=$order['order_actual_amount'];
        $insert['is_first']=$onceNum?CORRECT:DENY;
        $insert['create_time']=time();
        $insert['order_revenue_amount']=0;
        if ($insert['is_first']==CORRECT){
            $insert['order_calculation_type']=$goods['is_allocation_mode'];
            if ($goods['is_allocation_mode']==CORRECT){
                $insert['order_revenue_amount']=number_format($order['order_actual_amount']*$goods['allocation_rate'],2, '.', '');
            }elseif($goods['is_allocation_mode']==DENY){
                $insert['order_revenue_amount']=checkRuntimeEnv()?$goods['allocation_amount']:env_test_order_commission_amount;
            }
        }else{
            $insert['order_calculation_type']=$goods['is_repurchase_allocation_mode'];
            if ($goods['is_repurchase_allocation_mode']==CORRECT){
                $insert['order_revenue_amount']=number_format($order['order_actual_amount']*$goods['repurchase_allocation_rate'],2, '.', '');
            }elseif($goods['is_repurchase_allocation_mode']==DENY){
                $insert['order_revenue_amount']=$goods['repurchase_allocation_amount'];
                $insert['order_revenue_amount']=checkRuntimeEnv()?$goods['allocation_amount']:env_test_order_commission_amount;
            }
        }
        $insert['order_cost_amount']=$order['order_actual_amount']-$insert['order_revenue_amount'];
        //查询是否具有推广人
        if ($order['pid']){
            //查询用户是否已申请推荐官，并检索对应比例
            $promotionDistributionRate=DistributionOfficerModel::where([
                'member_id'=>$order['pid'],
                'status'   =>CORRECT
            ])->value('distribution_rate')?:0;
            $insert['order_promotion_rate']=$promotionDistributionRate;
            $insert['member_promotion_id']=$order['pid'];
            $insert['order_promotion_amount']=number_format($insert['order_revenue_amount']*$promotionDistributionRate,2,'.', '');
        }
        //保存数据
        return OrderDistributionModel::insertGetId($insert);
    }

    //维护待关闭订单操作
    public static function batchCloseUnpaidOrder(): bool
    {
        $orderIds=OrderModel::where([
//            'status'        =>CORRECT,
            'order_status'  =>order_status_0
        ])->pluck('id');
        foreach ($orderIds as $orderId){
            OrderService::closeUnpaidOrder($orderId);
        }
        return true;
    }

    //关闭指定待支付订单操作
    public static function closeUnpaidOrder(int $orderId): bool
    {
        $order=OrderModel::where([
            'id'            =>$orderId,
//            'status'        =>CORRECT,
            'order_status'  =>order_status_0
        ])->where('create_time',time()-unpaid_order_auto_cancel_interval,'<')->first();
        if (empty($order->id)){
            Logger::app('关闭待支付订单:无效订单ID');
            return false;
        }
        $order=$order->toArray();
        if (!empty($order['update_time'])){
            //检测变动时间是否符合自动关闭场景
            $surplusTime=((int)$order['update_time'] + unpaid_order_auto_cancel_interval)-time();
            if ($surplusTime){
                Logger::app('关闭待支付订单:不符合关闭条件','info',[$order['update_time'],$surplusTime]);
                return false;
            }
        }
        $ret=OrderModel::where([
            'id'            =>$orderId
        ])->update([
            'update_time'=>time(),
            'order_status'=>order_status_2
        ]);
        if (!$ret){
            Logger::app('关闭待支付订单:订单状态更新失败');
            return false;
        }
        return true;
    }

    //获取订单信息
    public static function getOrderInfo(int $orderId): array
    {
        $order=OrderModel::where([
            'id'            =>$orderId
        ])->first();
        if (empty($order->id)){
            return [];
        }
        return $order->toArray();
    }

    //订单退款进度
    public static function orderRefundProgress(int $memberId,int $orderId): array
    {
        //查看订单信息
        $order=OrderModel::where([
            'id'        =>$orderId,
            'member_id' =>$memberId
        ])->select(['id','goods_title','goods_icon','order_actual_amount'])->first();
        if (empty($order->id)){
            Logger::app('订单退款进度:无效订单ID');
            return formatReturnData(PARAMETER_ERROR,'该订单无效');
        }
        //查询退款信息
        $orderRefund=OrderRefundModel::where([
            'order_id'        =>$orderId,
        ])->select([
            'order_refund_sn','refund_id','order_receipt_amount','order_refund_amount','order_refund_status',
            'fail_reason','refund_time','create_time','handle_time','id','refund_rule_type','refund_recv_accout'
        ])->first();
        if (empty($orderRefund->id)){
            Logger::app('订单退款进度:无效订单ID');
            return formatReturnData(PARAMETER_ERROR,'该订单无效');
        }
        $orderRefund=$orderRefund->toArray();
        //标题
        $title='';
        if ($orderRefund['order_refund_status']==0){
            $title='等待处理';
        }elseif ($orderRefund['order_refund_status']==1){
            $title='处理中';
        }elseif ($orderRefund['order_refund_status']==2){
            if (in_array($orderRefund['refund_rule_type'],[refund_rule_1,refund_rule_2])){
                $title='已退款';
            }else{
                $title='已部分退款';
            }
        }elseif ($orderRefund['order_refund_status']==3){
            $title='退款失败，请联系客服处理';
        }
        //进度整理
        $refundPrecess[]=[
            'title'=>'退款申请已提交',
            'time' =>$orderRefund['create_time'],
            'remarks'=>''
        ];
        if (in_array($orderRefund['order_refund_status'],[1,2,3])){
            $refundPrecess[]=[
                'title'=>'退款申请已受理',
                'time' =>$orderRefund['handle_time'],
                'remarks'=>''
            ];
        }
        if ($orderRefund['order_refund_status'] == 2){
            $refundPrecess[]=[
                'title'=>'退款处理已完成',
                'time' =>$orderRefund['refund_time'],
                'remarks'=>''
            ];
        }
        if ($orderRefund['order_refund_status'] == 3){
            $refundPrecess[]=[
                'title'=>'退款处理失败',
                'time' =>$orderRefund['update_time'],
                'remarks'=>$orderRefund['fail_reason']?sprintf("失败原因:%s",$orderRefund['fail_reason']):''
            ];
        }

        //定义返回数据
        $data['order_refund_relation']=$order;
        $data['order_refund_status_title']=$title;
        $data['order_refund_sn']=$orderRefund['order_refund_sn'];
        $data['refund_id']=$orderRefund['refund_id'];
        $data['order_receipt_amount']=$orderRefund['order_receipt_amount'];
        $data['order_refund_amount']=$orderRefund['order_refund_amount'];
        $data['handle_time']=$orderRefund['handle_time'];
        $data['refund_recv_accout']=$orderRefund['refund_recv_accout'];
        $data['progress']=array_reverse($refundPrecess);
        return formatReturnSuccessData($data);
    }

    //减少库存信息
    public static function reduceStockNum($goodsId,$goodsPeriodId,$goodsNum=1): bool
    {
        Logger::app('减少库存信息：更新数据','info',[$goodsId,$goodsPeriodId,$goodsNum]);
        //操作商品表数据
        $ret=GoodsModel::where('id',$goodsId)->increment('goods_sale_num',$goodsNum);
        if (!$ret){
            Logger::app('减少库存信息：更新商品销量失败');
            return false;
        }
        $ret=GoodsModel::where('id',$goodsId)->decrement('goods_stock_num',$goodsNum);
        if (!$ret){
            Logger::app('减少库存信息：更新商品库存失败');
            return false;
        }
        if ($goodsPeriodId){
            $ret=GoodsPeriodModel::where('id',$goodsPeriodId)->increment('goods_sale_num',$goodsNum);
            if (!$ret){
                Logger::app('减少库存信息：更新营期商品销量失败');
                return false;
            }
            $ret=GoodsPeriodModel::where('id',$goodsPeriodId)->decrement('goods_stock_num',$goodsNum);
            if (!$ret){
                Logger::app('减少库存信息：更新营期商品库存失败');
                return false;
            }
        }
        Logger::app('减少库存信息：更新数据成功');
        return true;
    }

    //增加库存
    public static function addStockNum($goodsId,$goodsPeriodId,$goodsNum=1): bool
    {
        Logger::app('增加库存信息：更新数据','info',[$goodsId,$goodsPeriodId,$goodsNum]);
        //操作商品表数据
        $ret=GoodsModel::where('id',$goodsId)->increment('goods_stock_num',$goodsNum);
        if (!$ret){
            Logger::app('增加库存信息：更新商品库存失败');
            return false;
        }
        if ($goodsPeriodId){
            $ret=GoodsPeriodModel::where('id',$goodsPeriodId)->increment('goods_stock_num',$goodsNum);
            if (!$ret){
                Logger::app('增加库存信息：更新营期商品库存失败');
                return false;
            }
        }
        return true;
    }

    //自动更新可设置已消费订单
    public static function autoUpdateAllowFinishOrders(): bool
    {
        //本次日志关联标识
        $logId=md5(uniqid('ct'));
        //获取今日0点时间戳
        $time=strtotime("today midnight");
        Logger::app(sprintf('设置成消费订单(%s):获取今日0点时间戳',$logId),'info',[$time]);
        //获取可操作营期数组
        $goodsPeriodIds=GoodsPeriodModel::where('goods_period_date',$time)->pluck('id')->toArray();
        //获取符合消费营期
        $enableGoodsPeriodIds=OrderPeriodProcessModel::whereIn('goods_period_id',$goodsPeriodIds)
            ->where('status',CORRECT)
            ->pluck('goods_period_id')->toArray();
        //进行遍历循环
        foreach ($enableGoodsPeriodIds as $enableGoodsPeriodId){
            //查询符合操作数据
            $orderIds=OrderModel::where([
                'order_status'      =>order_status_1,
                'is_verification'   =>DENY,
                'is_refund'         =>CORRECT,
                'goods_period_id'   =>$enableGoodsPeriodId
            ])->pluck('id')->toArray();
            Logger::app(sprintf('设置成消费订单(%s):获取符合对账订单组',$logId),'info',$orderIds);
            if (empty($orderIds)){
                Logger::app(sprintf('设置成消费订单(%s):符合对账订单组为空',$logId));
                continue;
            }
            $ret=OrderModel::whereIn('id',$orderIds)->update([
                'order_status'      =>order_status_8,
                'is_verification'   =>CORRECT,
                'verification_time' =>time(),
                'update_time'       =>time()
            ]);
            if (!$ret){
                Logger::app(sprintf('设置成消费订单(%s):批量更新订单状态失败',$logId));
                continue;
            }
            $orderRevenues=OrderDistributionModel::whereIn('order_id',$orderIds)->where('status',CORRECT)->pluck('order_revenue_amount','order_id')->toArray();
            $orderTransactions=OrderModel::whereIn('id',$orderIds)->where('status',CORRECT)->pluck('order_transaction_id','id')->toArray();

            //生成分账控制信息
            $profitInserts=[];
            foreach ($orderIds as $orderId){
                $profitInserts[]=[
                    'order_id'=>$orderId,
                    'transaction_id'=>$orderTransactions[$orderId]??'',
                    'out_order_no'=>createOrderTradeNo(),
                    'profit_amount'=>$orderRevenues[$orderId]??0,
                    'create_time'=>time(),
                    'transfer_account_type' =>transfer_account_default['transfer_account_type'],
                    'transfer_account'      =>transfer_account_default['transfer_account'],
                    'transfer_account_name' =>transfer_account_default['transfer_account_name'],
                    'transfer_relation_type'=>transfer_account_default['transfer_relation_type']
                ];
            }
            Logger::app(sprintf('生成对账单(%s):生成分账控制信息数据',$logId),'info',$profitInserts);
            //增加分账进程控制
            $ret=OrderProfitProcessModel::insert($profitInserts);
            if (!$ret){
                Logger::app(sprintf('生成对账单(%s):生成分账控制信息失败',$logId));
                continue;
            }
            //进行分账账户设置
            foreach ($orderIds as $orderId){
                Client::send(AUTO_HANDLE_ORDER_PROFIT_QUEUE, ['order_id'=>$orderId], 5);
                Logger::app(sprintf('设置成消费订单(%s):设置分账用户设置队列',$logId),'info',[$orderId]);
            }
            Logger::app(sprintf('设置成消费订单(%s):结果成功',$logId),'info',['order_id'=>$orderIds]);
        }
        return true;
    }


}